package com.cy.pj.common.config;

import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.LinkedHashMap;

@Configuration
public class SpringShiroConfig {
    /**
     * SecurityManager是shiro框架的核心
     * @return
     */
    @Bean
    public SecurityManager securityManager(Realm realm,
                                           CacheManager cacheManager,
                                           RememberMeManager rememberMeManager,
                                           SessionManager sessionManager) {
        DefaultWebSecurityManager sManager = new DefaultWebSecurityManager();
        sManager.setRealm(realm);
        sManager.setCacheManager(cacheManager);
        sManager.setRememberMeManager(rememberMeManager);
        sManager.setSessionManager(sessionManager);
        return sManager;
    }

    // shiro.apache.org

    /**
     * 配置ShiroFilterFactoryBean对象并指定过滤规则，创建过滤器工厂
     * 过滤器是javaee规范中的请求处理的入口
     * @param sManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactory(SecurityManager sManager) {
        ShiroFilterFactoryBean sfBean = new ShiroFilterFactoryBean();
        sfBean.setSecurityManager(sManager);// 判定访问这个资源是是否通过认证
        sfBean.setLoginUrl("/doLoginUI");// 跳转到认证资源
        LinkedHashMap<String, String> map = new LinkedHashMap<>();// 记录规则，要求有顺序
        // map中规则：key为资源名称，value为规则
        // /bower_components/**表示：bower_components目录及子目录下的所有资源
        // 测试访问任一js文件：localhost/bower_components/chart.js/gulpfile.js
        map.put("/bower_components/**", "anon");// anon表示：匿名访问
        map.put("/build/**", "anon");
        map.put("/dist/**", "anon");
        map.put("/plugins/**", "anon");
        map.put("/doIndexUI", "anon");// 允许匿名访问首页
        map.put("/user/doLogin", "anon");// 放行登录操作 允许登录
        map.put("/doLogout", "logout");// 当value为logout时，退出时会自动回到登录界面
        //map.put("/**", "authc");// 除了以上资源，其他资源需要认证访问
        map.put("/**", "user");// 此方式的认证还可以从客户端的cookie取用户信息
        //map.put("/**", "anon");//
        sfBean.setFilterChainDefinitionMap(map);
        return sfBean;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        return new DefaultAdvisorAutoProxyCreator();
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager sManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(sManager);
        return advisor;
    }

    /**
     * 对于已认证用户而言，默认每次进行授权方法的访问，都需要从数据库中查询用户的权限信息
     * 这部分信息相对比较稳定，但是频繁访问数据库获取这部分信息可能会在性能上有一定的影响
     * 缓存登场
     * @return
     */
    @Bean
    public CacheManager cacheManager() {
        return new MemoryConstrainedCacheManager();/* 配置shiro缓存管理器  这个是内置缓存 以后可用redis框架 */
    }

    /**
     * 记住我
     *
     * cookie类似于生活中的理发卡、洗车卡等
     *
     * @return
     */
    @Bean
    public RememberMeManager rememberMeManager() {
        CookieRememberMeManager cManager = new CookieRememberMeManager();
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        cookie.setMaxAge(7*24*60*60);// 7天
        cManager.setCookie(cookie);
        return cManager;
    }

    /**
     * 会话
     * @return
     */
    @Bean
    public SessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(2 * 1800000L);// 设置超时：30分钟
        //sessionManager.setSessionIdUrlRewritingEnabled(true);
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }
}
